% 坐标
-record(fc_point, {x = 0, y = 0}).

create_fc_point(X, Y) ->
    #fc_point{x = X, y = Y}.

% 尺寸大小
-record(fc_size, {cx = 0, cy = 0}).

create_fc_size(CX, CY) ->
    #fc_size{cx = CX, cy = CY}.

% 矩形区域
-record(fc_rect, {left = 0, top = 0, right = 0, bottom = 0}).

create_fc_rect(Left, Top, Right, Bottom) ->
    #fc_rect{left = Left, top = Top, right = Right, bottom = Bottom}.

% 边距信息
-record(fc_padding, {left = 0, top = 0, right = 0, bottom = 0}).

create_fc_padding(Left, Top, Right, Bottom) ->
    #fc_padding{left = Left, top = Top, right = Right, bottom = Bottom}.

% 绘图相关
-record(fc_paint, {
          cancel_click = false,
          default_ui_style = "light",
          drag_begin_point = #fc_point{x = 0, y = 0},
          drag_begin_rect = #fc_rect{left = 0, top = 0, right = 0, bottom = 0},
          dragging_view = undefined,
          editing_text_box = undefined,
          first_touch = false,
          focused_view = undefined,
          is_double_click = false,
          is_mobile = false,
          is_path = false,
          last_click_time = 0,
          move_to = false,
          offset_x = 0.0,
          offset_y = 0.0,
          ratio = 1,
          resize_column_state = 0.0,
          resize_column_begin_width = 0.0,
          resize_column_index = -1,
          scale_factor_x = 1.0,
          scale_factor_y = 1.0,
          second_touch = false,
          system_font = "Arial",
          touch_down_point = #fc_point{x = 0, y = 0},
          touch_first_point = #fc_point{x = 0, y = 0},
          touch_second_point = #fc_point{x = 0, y = 0},
          touch_down_view = undefined,
          touch_move_view = undefined,
          views = []
         }).

add_line(FCPaintRec, X1, Y1, X2, Y2) ->
    ok.

begin_path(FCPaintRec) ->
    ok.

begin_paint(FCPaintRec, RectRec) ->
    ok.

close_figure(FCPaintRec) ->
    ok.

close_path(FCPaintRec) ->
    ok.

draw_line(FCPaintRec, Color, Width, Style, X1, Y1, X2, Y2) ->
    ok.

draw_path(FCPaintRec, Color, Width, Style) ->
    ok.

draw_polyline(FCPaintRec, Color, Width, Style, AptList) ->
    ok.

draw_polygon(FCPaintRec, Color, Width, Style, AptList) ->
    ok.

draw_image(FCPaintRec, Image, Left, Top, Right, Bottom) ->
    ok.

draw_rect(FCPaintRec, Color, Width, Style, Left, Top, Right, Bottom) ->
    ok.

draw_ellipse(FCPaintRec, Color, Width, Style, Left, Top, Right, Bottom) ->
    ok.

draw_round_rect(FCPaintRec, Color, Width, Style, Left, Top, Right, Bottom, CornerRadius) ->
    ok.

draw_text(FCPaintRec, Text, Color, Font, X, Y) ->
    ok.

end_paint(FCPaintRec) ->
    ok.

fill_path(FCPaintRec, Color) ->
    ok.

fill_polygon(FCPaintRec, Color, AptList) ->
    ok.

fill_rect(FCPaintRec, Color, Left, Top, Right, Bottom) ->
    ok.

fill_round_rect(FCPaintRec, Color, Left, Top, Right, Bottom, CornerRadius) ->
    ok.

fill_ellipse(FCPaintRec, Color, Left, Top, Right, Bottom) ->
    ok.

set_clip(FCPaintRec, Left, Top, Right, Bottom) ->
    ok.

set_offset(FCPaintRec, X, Y) ->
    NewFCPaintRec = FCPaintRec#fc_paint{offset_x = X, offset_y = Y},
    NewFCPaintRec.

text_size(FCPaintRec, Text, Font) ->
    create_fc_size(0, 0).

save(FCPaintRec) ->
    ok.

restore(FCPaintRec) ->
    ok.

draw_text_auto_ellipsis(FCPaintRec, Text, Color, Font, Left, Top, Right, Bottom) ->
    case Text of
        [] ->
            ok;
        _ ->
            TSize = text_size(FCPaintRec, Text, Font),
            case TSize#fc_size.cx < Right - Left of
                true ->
                    draw_text(FCPaintRec, Text, Color, Font, Left, Top);
                false ->
                    case TSize#fc_size.cx > 0 of
                        true ->
                            SubLen = 3,
                            loop(Text, Font, Left, Top, Right, Bottom, SubLen);
                        false ->
                            ok
                    end
            end
    end.

loop(Text, Font, Left, Top, Right, Bottom, SubLen) ->
    NewLen = length(Text) - SubLen,
    case NewLen > 0 of
        true ->
            NewText = lists:sublist(Text, NewLen) ++ "...",
            TSize = text_size(FCPaintRec, NewText, Font),
            case TSize#fc_size.cx < Right - Left of
                true ->
                    draw_text(FCPaintRec, NewText, Color, Font, Left, Top);
                false ->
                    loop(Text, Font, Left, Top, Right, Bottom, SubLen + 3)
            end;
        false ->
            ok
    end.

-record(attr_pair, {key = "", value = ""}).

% 基础视图
-record(fc_view, {
          allow_drag = false,
          allow_resize = false,
          align = "left",
          allow_drag_scroll = true,
          allow_previews_event = false,
          back_color = "rgb(255,255,255)",
          border_color = "rgb(150,150,150)",
          border_width = 1,
          clip_rect = #fcrect{left = 0, top = 0, right = 0, bottom = 0},
          corner_radius = 0,
          cursor = "",
          down_scroll_h_button = false,
          down_scroll_v_button = false,
          display_offset = true,
          dock = "none",
          enabled = true,
          ex_attributes = [], 
          font = "Default,12",
          hovered_color = undefined,
          hover_scroll_h_button = false,
          hover_scroll_v_button = false,
          h_scroll_is_visible = false,
          location = #fc_point{x = 0, y = 0},
          margin = #fcpadding{left = 0, top = 0, right = 0, bottom = 0},
          maximum_size = #fc_size{cx = 0, cy = 0},
          padding = #fcpadding{left = 0, top = 0, right = 0, bottom = 0},
          paint = undefined,
          parent = undefined,
          pushed_color = "rgb(100,100,100)",
          resize_point = -1,
          scroll_v = 0.0,
          scroll_h = 0.0,
          scroll_size = 8.0,
          show_h_scroll_bar = false,
          show_v_scroll_bar = false,
          scroll_bar_color = "rgb(200,200,200)",
          scroll_bar_hovered_color = "rgb(42,138,195)",
          size = #fc_size{cx = 0, cy = 0},
          start_scroll_h = 0.0,
          start_scroll_v = 0.0,
          start_point = #fc_point{x = 0, y = 0},
          start_rect = #fcrect{left = 0, top = 0, right = 0, bottom = 0},
          tab_index = 0,
          tab_stop = false,
          text = "",
          text_color = "rgb(0,0,0)",
          text_align = "left",
          top_most = false,
          touch_down_time = 0,
          view_name = "",
          visible = true,
          vertical_align = "top",
          view_type = "none",
          v_scroll_is_visible = false,
          views = []
         }).

create_fc_view() ->
    #fc_view{}.

% 添加顶层视图
add_view(View, Paint) ->
    NewView = View#fc_view{paint = Paint},
    NewPaint = Paint#fc_paint{views = [NewView | Paint#fc_paint.views]},
    {NewView, NewPaint}.

% 添加到父视图
add_view_to_parent(View, Parent) ->
    NewView = View#fc_view{paint = Parent#fc_view.paint},
    Views = case Parent#fc_view.views of
                [] -> [View];
                _ -> [View | Parent#fc_view.views]
            end,
    NewParent = Parent#fc_view{views = Views},
    NewViewWithParent = View#fc_view{parent = NewParent},
    {NewViewWithParent, NewParent}.

% 清除视图
clear_views(Paint) ->
    Paint#fc_paint{views = []}.

% 移除顶层视图
remove_view(View, Paint) ->
    Views = Paint#fc_paint.views,
    case Views of
        [] ->
            {View, Paint};
        _ ->
            NewViews = remove_view_helper(View, Views, []),
            NewPaint = Paint#fc_paint{views = NewViews},
            {View, NewPaint}
    end.
remove_view_helper(_, [], Removed) ->
    Removed;
remove_view_helper(View, [H | T], Removed) ->
    case H =:= View of
        true ->
            Removed ++ T;
        false ->
            remove_view_helper(View, T, Removed ++ [H])
    end.

% 从父视图中移除
remove_view_from_parent(View, Parent) ->
    Views = Parent#fc_view.views,
    case Views of
        [] ->
            {View, Parent};
        _ ->
            NewViews = remove_view_helper(View, Views, []),
            NewParent = Parent#fc_view{views = NewViews},
            {View, NewParent}
    end.

% 获取绝对位置X
client_x(View) ->
    case View of
        undefined ->
            0;
        _ ->
            CLeft = View#fc_view.location#fc_point.x,
            case View#fc_view.parent of
                undefined ->
                    CLeft;
                Parent ->
                    case Parent#fc_view.display_offset andalso Parent#fc_view.scroll_h > 0 of
                        true ->
                            CLeft + client_x(Parent) - Parent#fc_view.scroll_h;
                        false ->
                            CLeft + client_x(Parent)
                    end
            end
    end.

% 获取绝对位置Y
client_y(View) ->
    case View of
        undefined ->
            0;
        _ ->
            CTop = View#fc_view.location#fc_point.y,
            case View#fc_view.parent of
                undefined ->
                    CTop;
                Parent ->
                    case Parent#fc_view.display_offset andalso Parent#fc_view.scroll_v > 0 of
                        true ->
                            CTop + client_y(Parent) - Parent#fc_view.scroll_v;
                        false ->
                            CTop + client_y(Parent)
                    end
            end
    end.

% 是否包含坐标
contains_point(View, Mp) ->
    case is_view_enabled(View) of
        true ->
            Clx = client_x(View),
            Cly = client_y(View),
            Size = View#fc_view.size,
            Cp = #fc_point{x = Mp#fc_point.x - Clx, y = Mp#fc_point.y - Cly},
            Cp#fc_point.x >= 0 andalso Cp#fc_point.x =< Size#fc_size.cx andalso
            Cp#fc_point.y >= 0 andalso Cp#fc_point.y =< Size#fc_size.cy;
        false ->
            false
    end.

% 判断视图是否可用
is_view_enabled(View) ->
    case View of
        undefined ->
            false;
        _ ->
            View#fc_view.enabled andalso
            (case View#fc_view.parent of
                 undefined ->
                     true;
                 Parent ->
                     is_view_enabled(Parent)
             end)
    end.

% 查找有预处理事件的父视图
find_previews_event_parent(View) ->
    case View of
        undefined ->
            undefined;
        _ ->
            case View#fc_view.allow_previews_event of
                false ->
                    case View#fc_view.parent of
                        undefined ->
                            undefined;
                        Parent ->
                            case Parent#fc_view.allow_previews_event of
                                true ->
                                    Parent;
                                false ->
                                    find_previews_event_parent(Parent)
                            end
                    end;
                true ->
                    undefined
            end
    end.

% 根据名称查找视图
find_view_by_name(Name, Views) ->
    find_view_by_name_helper(Name, Views).
find_view_by_name_helper(_, []) ->
    undefined;
find_view_by_name_helper(Name, [H | T]) ->
    case H#fc_view.view_name =:= Name of
        true ->
            H;
        false ->
            case H#fc_view.views of
                [] ->
                    find_view_by_name_helper(Name, T);
                _ ->
                    case find_view_by_name_helper(Name, H#fc_view.views) of
                        undefined ->
                            find_view_by_name_helper(Name, T);
                        SubView ->
                            SubView
                    end
            end
    end.

% 根据坐标查找视图
find_view(Mp, Views) ->
    find_view_helper(Mp, Views, true).
find_view_helper(_, [], _) ->
    undefined;
find_view_helper(Mp, Views, TopMostFlag) ->
    Size = length(Views),
    find_view_loop(Mp, Views, Size - 1, TopMostFlag).
find_view_loop(_, _, -1, _) ->
    undefined;
find_view_loop(Mp, Views, I, TopMostFlag) ->
    View = lists:nth(I + 1, Views),
    case View#fc_view.visible andalso (View#fc_view.top_most =:= TopMostFlag) of
        true ->
            HasPoint = contains_point(View, Mp),
            case HasPoint of
                true ->
                    case View#fc_view.v_scroll_is_visible andalso View#fc_view.scroll_size > 0 of
                        true ->
                            Clx = client_x(View),
                            case Mp#fc_point.x >= Clx + View#fc_view.size#fc_size.cx - View#fc_view.scroll_size of
                                true ->
                                    View;
                                false ->
                                    case View#fc_view.h_scroll_is_visible andalso View#fc_view.scroll_size > 0 of
                                        true ->
                                            Cly = client_y(View),
                                            case Mp#fc_point.y >= Cly + View#fc_view.size#fc_size.cy - View#fc_view.scroll_size of
                                                true ->
                                                    View;
                                                false ->
                                                    case View#fc_view.views of
                                                        [] ->
                                                            View;
                                                        _ ->
                                                            case find_view(Mp, View#fc_view.views) of
                                                                undefined ->
                                                                    View;
                                                                SubView ->
                                                                    SubView
                                                            end
                                                    end
                                        false ->
                                            case View#fc_view.views of
                                                [] ->
                                                    View;
                                                _ ->
                                                    case find_view(Mp, View#fc_view.views) of
                                                        undefined ->
                                                            View;
                                                        SubView ->
                                                            SubView
                                                    end
                                            end
                                    end
                        false ->
                            case View#fc_view.views of
                                [] ->
                                    View;
                                _ ->
                                    case find_view(Mp, View#fc_view.views) of
                                        undefined ->
                                            View;
                                        SubView ->
                                            SubView
                                    end
                            end
                    end;
                false ->
                    find_view_loop(Mp, Views, I - 1, TopMostFlag)
            end;
        false ->
            find_view_loop(Mp, Views, I - 1, TopMostFlag)
    end.

% 是否重绘时可见
is_paint_visible(View) ->
    case View#fc_view.visible of
        true ->
            case View#fc_view.parent of
                undefined ->
                    true;
                Parent ->
                    case Parent#fc_view.visible of
                        true ->
                            is_paint_visible(Parent);
                        false ->
                            false
                    end
            end;
        false ->
            false
    end.

% 是否视图可用
is_view_enabled(View) ->
    case View#fc_view.enabled of
        true ->
            case View#fc_view.parent of
                undefined ->
                    true;
                Parent ->
                    case Parent#fc_view.enabled of
                        true ->
                            is_view_enabled(Parent);
                        false ->
                            false
                    end
            end;
        false ->
            false
    end.

% 获取区域的交集
get_intersect_rect(DestRect, Src1Rect, Src2Rect) ->
    NewLeft = max(Src1Rect#fcrect.left, Src2Rect#fcrect.left),
    NewRight = min(Src1Rect#fcrect.right, Src2Rect#fcrect.right),
    NewTop = max(Src1Rect#fcrect.top, Src2Rect#fcrect.top),
    NewBottom = min(Src1Rect#fcrect.bottom, Src2Rect#fcrect.bottom),
    case NewRight > NewLeft andalso NewBottom > NewTop of
        true ->
            1;
        false ->
            DestRect1 = DestRect#fcrect{left = 0, right = 0, top = 0, bottom = 0},
            {DestRect1, 0}
    end.

% 重绘视图
render_views(Views, Paint, Rect) ->
    render_views_loop(Views, Paint, Rect, false).
render_views_loop([], _, _, _) ->
    ok;
render_views_loop(Views, Paint, Rect, TopMostFlag) ->
    Size = length(Views),
    render_views_inner_loop(Views, Paint, Rect, Size, TopMostFlag).
render_views_inner_loop(_, _, _, 0, _) ->
    ok;
render_views_inner_loop(Views, Paint, Rect, I, TopMostFlag) ->
    View = lists:nth(I, Views),
    case Rect of
        undefined ->
            case View#fc_view.views of
                [] ->
                    ok;
                _ ->
                    SubSize = length(View#fc_view.views),
                    case SubSize > 0 of
                        true ->
                            render_views(View#fc_view.views, Paint, undefined);
                        false ->
                            ok
                    end
            end,
            View1 = View#fc_view{clip_rect = undefined},
            render_views_inner_loop(Views, Paint, Rect, I - 1, TopMostFlag);
        _ ->
            case TopMostFlag =:= View#fc_view.top_most andalso is_paint_visible(View) of
                true ->
                    Clx = client_x(View),
                    Cly = client_y(View),
                    DrawRect = #fcrect{left = 0, top = 0, right = View#fc_view.size#fc_size.cx, bottom = View#fc_view.size#fc_size.cy},
                    ClipRect = #fcrect{left = Clx, top = Cly, right = Clx + View#fc_view.size#fc_size.cx, bottom = Cly + View#fc_view.size#fc_size.cy},
                    DestRect = #fcrect{left = 0, top = 0, right = 0, bottom = 0},
                    case get_intersect_rect(DestRect, Rect, ClipRect) of
                        {_, 0} ->
                            case View#fc_view.views of
                                [] ->
                                    ok;
                                _ ->
                                    SubSize = length(View#fc_view.views),
                                    case SubSize > 0 of
                                        true ->
                                            render_views(View#fc_view.views, Paint, undefined);
                                        false ->
                                            ok
                                    end
                            end,
                            View1 = View#fc_view{clip_rect = undefined},
                            render_views_inner_loop(Views, Paint, Rect, I - 1, TopMostFlag);
                        {DestRect1, 1} ->
                            paint_save(Paint),
                            paint_set_offset(Paint, 0, 0),
                            paint_set_clip(Paint, DestRect1#fcrect.left, DestRect1#fcrect.top, DestRect1#fcrect.right, DestRect1#fcrect.bottom),
                            View1 = View#fc_view{clip_rect = DestRect1},
                            paint_set_offset(Paint, Clx, Cly),
                            case View#fc_view.views of
                                [] ->
                                    ok;
                                _ ->
                                    SubSize = length(View#fc_view.views),
                                    case SubSize > 0 of
                                        true ->
                                            render_views(View#fc_view.views, Paint, DestRect1);
                                        false ->
                                            ok
                                    end
                            end,
                            paint_set_offset(Paint, Clx, Cly),
                            paint_restore(Paint),
                            render_views_inner_loop(Views, Paint, Rect, I - 1, TopMostFlag)
                    end;
                false ->
                    render_views_inner_loop(Views, Paint, Rect, I - 1, TopMostFlag)
            end
    end.

% 全局刷新
invalidate(Paint) ->
    ok.

% 刷新视图
invalidate_view(View) ->
    ok.